package server;

import mapper.MapperContext;
import mapper.MapperHost;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class Bootstrap {

    //private int port = 8080;
    //private Map<String,HttpServlet> servletMap=new HashMap<>();
    private List<MapperHost> hosts = new ArrayList<>();
//    public int getPort() {
//        return port;
//    }
//
//    public void setPort(int port) {
//        this.port = port;
//    }

    //public List<Map>

    /**
     * Minicat启动需要初始化展开的一些操作
     */
    public void start() throws IOException, DocumentException {
        //加载解析配置文件 3.0配置
        //loadServlet();

        //初始化 4.0配置
        loadServerXML();
        for (MapperHost host : hosts) {
            //绑定端口
            ServerSocket socket = new ServerSocket();
            socket.bind(new InetSocketAddress(host.getPort()));
            System.out.println("======>>>Minicat start port: "+host.getPort());

            while (true) {
                Socket accept = socket.accept();
                System.out.println("======>>>Minicat get info");

                InputStream inputStream = accept.getInputStream();
                //封装Request
                Request request=new Request(inputStream);
                String method = request.getMethod();
                String url = request.getUrl();

                String[] urlInfo = url.split("/");
                String urlContext ="";
                String urlservletOrPage = "";
                if (urlInfo.length > 2) {
                    urlContext = urlInfo[1];
                    urlservletOrPage = "/"+urlInfo[2];
                }
                //接收到请求
                OutputStream outputStream = accept.getOutputStream();
                Response response = new Response(outputStream);

                for (MapperContext context:host.getContexts()) {
                    if(context.getName().equals(urlContext)){
                        Map<String, HttpServlet> wrapperMap = context.getWrapperMap();
                        if(wrapperMap.get(urlservletOrPage)==null){
                            response.outputHtml(context.getContextFilePath() + "/" + urlservletOrPage);
                        }else{
                            HttpServlet httpServlet = wrapperMap.get(urlservletOrPage);
                            httpServlet.service(request,response);
                        }
                        break;
                    }
                }
                accept.close();
            }
        }



        /*ServerSocket socket = new ServerSocket();
        socket.bind(new InetSocketAddress(port));
        System.out.println("======>>>Minicat start port: "+port);*/

        //1.0版本
        /*while (true) {
            Socket accept = socket.accept();
            System.out.println("======>>>Minicat get info");
            String res=HttpProtocolUtil.getHttpHeader200("Hello Minicat");
            //接收到请求
            OutputStream outputStream = accept.getOutputStream();
            outputStream.write(res.getBytes());
            accept.close();
        }*/


        /*while (true) {
            Socket accept = socket.accept();
            System.out.println("======>>>Minicat get info");
            InputStream inputStream = accept.getInputStream();
            int count=0;
            //因为网络特性，有可能请求到了，但数据还没到，那么inputStream.available()可能等于0
            while (count==0){
                count=inputStream.available();
            }
            byte[] bytes=new byte[count];
            //把流当中的数据，读取到数组
            inputStream.read(bytes);
            System.out.println("====>请求信息："+new String(bytes));


            String res=HttpProtocolUtil.getHttpHeader200("Hello Minicat");
            //接收到请求
            OutputStream outputStream = accept.getOutputStream();
            outputStream.write(res.getBytes());
            accept.close();
        }*/

        /*while (true) {
            Socket accept = socket.accept();
            System.out.println("======>>>Minicat get info");

            InputStream inputStream = accept.getInputStream();
            Request request=new Request(inputStream);
            String method = request.getMethod();
            String url = request.getUrl();

            //接收到请求
            OutputStream outputStream = accept.getOutputStream();
            Response response=new Response(outputStream);

            response.outputHtml(url);

            accept.close();
        }*/

        //3.0
        /*while (true) {
            Socket accept = socket.accept();
            System.out.println("======>>>Minicat get info");

            InputStream inputStream = accept.getInputStream();
            //封装Request
            Request request=new Request(inputStream);
            String method = request.getMethod();
            //接收到请求
            OutputStream outputStream = accept.getOutputStream();
            Response response=new Response(outputStream);

            String url = request.getUrl();
            if(servletMap.get(url)==null){
                response.outputHtml(url);
            }else{
                HttpServlet httpServlet = servletMap.get(url);
                httpServlet.service(request,response);
            }
            accept.close();
        }*/



    }


    /**
     * 加载解析web.xml，初始化Servlet
     */
   /* private void loadServlet() {
        InputStream resourceAsStream
                = this.getClass().getClassLoader().getResourceAsStream("web.xml");
        SAXReader saxReader=new SAXReader();
        try {
            Document document=saxReader.read(resourceAsStream);
            Element rootElement = document.getRootElement();
            List<Element> list = rootElement.selectNodes("//servlet");
            for (int i = 0; i < list.size(); i++) {
                Element element=list.get(i);
                Element servletnameElement=(Element)element.selectSingleNode("servlet-name");
                String servletname = servletnameElement.getStringValue();
                Element servletclassElement=(Element)element.selectSingleNode("servlet-class");
                String servletclass = servletclassElement.getStringValue();

                //根据servlet-name的值找url-pattern
                Element servletMapping = (Element)rootElement.selectSingleNode("/web-app/servlet-mapping[servlet-name='" + servletname + "']");
                String urlPattern = servletMapping.selectSingleNode("url-pattern").getStringValue();
                servletMap.put(urlPattern,(HttpServlet)Class.forName(servletclass).newInstance());
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
    }*/

    /**
     * 加载server.xml
     */
    private void loadServerXML() throws DocumentException {
        // 加载server.xml文件
        InputStream resourceAsStream
                = this.getClass().getClassLoader().getResourceAsStream("server.xml");
        // 解析server.xml
        SAXReader saxReader=new SAXReader();
        Document document=saxReader.read(resourceAsStream);
        Element rootElement = document.getRootElement();
        // 解析Service
        List<Element> serviceList = rootElement.selectNodes("//Service");
        for (int i = 0; i < serviceList.size(); i++) {
            Element element = serviceList.get(i);
            Element connectorElement = (Element) element.selectSingleNode("Connector");
            // 获取Service的监听端口
            int connectorPort = new Integer(connectorElement.attributeValue("port")).intValue();
            Element hostElement = (Element) element.selectSingleNode("//Engine//Host");
            // 获取Service的主机名以及应用部署路径
            String hostName = hostElement.attributeValue("name");
            String hostAppBase = hostElement.attributeValue("appBase");
            MapperHost host = new MapperHost(hostName, hostAppBase, connectorPort);
            hosts.add(host);
        }
    }

    /**
     * Minicat的启动入口
     *
     * @param args
     */
    public static void main(String[] args)  {
        Bootstrap bootstrap=new Bootstrap();
        try {
            bootstrap.start();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (DocumentException e) {
            e.printStackTrace();
        }

    }
}
